/**
 * Created by sky on 2019/3/8.
 */
layui.define(['CommonProtoBuf3', 'CommonProto3', 'layer', 'zepto'], function (exports) {
    var CommonProtoBuf3 = layui.CommonProtoBuf3;
    var CommonProto3 = layui.CommonProto3;
    var layer = layui.layer;
    var $ = layui.zepto;
    var websocketcbObj = {};
    function CommonSocket(name, url, params, eventCallback, initCallBack, onCloseCallback, onSucceedCallback, websocketObj) {
        var self = this;
        self.url = url;
        self.params = params;
        self.webSocket = null;
        self.name = name;
        //心跳参数
        self.timeout = 7000; //心跳包时间7秒
        self.reconnectTimeout = 21000; //重连时间21秒
        self.needReconnect = true;
        /*   self.CommonPrefabMgr = require('CommonPrefabMgr');
         self.Language = require('Language');*/
        self.proto = new CommonProtoBuf3(CommonProto3, 'CommonProto3.proto', {});
        self.heartBeat = 100;
        self.last_ping = Date.parse(new Date()) / 1000;
        self.last_pang = Date.parse(new Date()) / 1000;
        self.reConnectCount = 0; //重连次数
        self.isInHeartCheck = false; //是否在心跳监测中
        self.reConnectState = 0;
        websocketcbObj = websocketObj || {}
        
        //socket回调
        if (typeof (eventCallback) == "function") {
            self.msgCallback = eventCallback;
        }
        if (typeof (initCallBack) == "function") {
            self.initCallBack = initCallBack;
        }
        if (typeof (onCloseCallback) == "function") {
            self.onCloseCallback = onCloseCallback;
        }
        if (typeof (onSucceedCallback) == "function") {
            self.onSucceedCallback = onSucceedCallback;
        }
        //重试参数
        self.tryTimeout = 5000; //socket重试时间5秒
        self.reconnect1 = -1; //重试定时器

        self.tag = 0;

        self.init();

    }

    CommonSocket.prototype.init = function () {
        var self = this;
        self.reConnectCount = 0;
        self.initWs();
        self.initEventHandle();

        //以下的代码，是为了修复setInterval定时不准（js单线程）造成的，瞬间多次执行（不能按照预期定时）的问题。
        function retryLogic() {
            console.log("retry");
            self.initWs();
            self.initEventHandle();
        }

        self.interRetry = setTimeout(function () {
            retryLogic();
            self.interRetry2 = setTimeout(retryLogic, self.tryTimeout);
        }, self.tryTimeout);
    };

    CommonSocket.prototype.initWs = function () {
        var self = this;
        console.log('Websocket(' + self.name + ')init:' + JSON.stringify(self.params));
        if (self.webSocket != null) {
          console.log('webSocketclose')
            self.webSocket.close();
            self.webSocket = null;
            console.log('webSocketnull')
        }
        if (!self.webSocket) {
          console.log('webSocketnew')
          self.webSocket = null;
            self.webSocket = new WebSocket(self.url);
            self.needReconnect = true;
            if (typeof (self.onSucceedCallback) == "function") {
                self.onSucceedCallback();
            }
        }
    };

    CommonSocket.prototype.initEventHandle = function () {
        var self = this;
        if (self.webSocket) {
            self.webSocket.onopen = function () {
                self.reConnectCount = 0;
                clearInterval(self.interRetry);
                clearInterval(self.interRetry2);
                clearInterval(self.reconnect1);
                if (self.webSocket && self.webSocket.binaryType) {
                    self.webSocket.binaryType = 'arraybuffer';
                }
                if (typeof (self.initCallBack) == "function") {
                    self.initCallBack();
                }

                if(typeof websocketcbObj.onSuccessCallback == 'function'){
                    
                    websocketcbObj.onSuccessCallback();
                }

                //启动心跳
                self.startHeartCheck();
                if (self.reConnectState != 0) {
                    console.log('Websocket(' + self.name + '),reconnect!---' + self.readyState);
                    //重连成功
                    self.reConnectState = 0;
                }
            };

            self.webSocket.onerror = function () {
                clearInterval(self.interRetry);
                clearInterval(self.interRetry2);
                console.log('Websocket(' + self.name + '),on error!---' + self.readyState);
            };

            self.webSocket.onclose = function (event) {
                clearInterval(self.interRetry);
                clearInterval(self.interRetry2);

                if(typeof websocketcbObj.onCloseCallback == 'function'){
                    websocketcbObj.onCloseCallback();
                }

                if (typeof (self.onCloseCallback) == "function") {
                    self.onCloseCallback();
                }
                if (self.webSocket != null) {
                    console.log('Websocket(' + self.name + '),on close!---' + self.readyState + ',errorCode:' + event.code);
                    self.webSocket.close();
                    self.webSocket = null;
                } else {
                    console.log('Websocket is null(' + self.name + '),on close!---');
                }
            };

            self.webSocket.onmessage = function (event) {
                console.log('Websocket(' + self.name + ') on message!---');
                if (self.reConnectState == 0) { //reConnectState == 1 出现在弱网环境下，此时忽略 onmessage
                    clearInterval(self.interRetry);
                    clearInterval(self.interRetry2);
                    clearInterval(self.reconnect1);
                    //记录pang
                    self.last_pang = Date.parse(new Date()) / 1000;
                    if (self.msgCallback) {
                        self.msgCallback(event.data);
                    }
                }
            };
        }
    };

    CommonSocket.prototype.send = function (msg) {
        var self = this;
        // console.log('Websocket(' + self.name + '),send:' + msg.toString());
        if (self.webSocket != null && self.webSocket.readyState === WebSocket.OPEN) {
            self.webSocket.send(msg);
            self.last_ping = Date.parse(new Date()) / 1000;
        }
    };

    CommonSocket.prototype.changeReconnectStatus = function (status) {
        var self = this;
        self.needReconnect = status;
    };

    CommonSocket.prototype.getReadyState = function () {
        var self = this;
        var wsStatus = null;
        if (self.webSocket) {
            wsStatus = self.webSocket.readyState;
        }
        return wsStatus;
    };

    CommonSocket.prototype.close = function () {
        var self = this;
        console.log("WebSocket(" + self.name + "), close.");
        //清空心跳定时
        clearInterval(self.interHeart);
        self.isInHeartCheck = false;
        self.last_ping = Date.parse(new Date()) / 1000;
        self.last_pang = Date.parse(new Date()) / 1000;
        if (self.webSocket) {
            self.needReconnect = false;
            self.webSocket.close();
            self.webSocket = null;
        }
    };

    CommonSocket.prototype.startHeartCheck = function () {
        var self = this;
        if (self.isInHeartCheck == false) {
            //清空心跳定时
            clearInterval(self.interHeart);
            console.log("heart check.");
            self.isInHeartCheck = true;
            var heartCallback = function () {
                console.log("heart logic.---》" + self.name);
                var now = Date.parse(new Date()) / 1000;
                var timeout_s = self.timeout / 1000;
                console.log("heart now:" + now);
                console.log("heart last_ping:" + self.last_ping);
                var isNeedPing = (now - self.last_ping) >= timeout_s;
                if (isNeedPing) {
                    var nowTimer = new Date().getTime();
                    var data = {
                        Timestamp: nowTimer
                    };
                    console.log("heart ping." + self.name);
                    self.commonProto3Send(0, "msg.Ping", data);
                }

                console.log("heart last_pang:" + self.last_pang);
                var reconnectTimeout_s = self.reconnectTimeout / 1000;
                var isResponseTimeout = (now - self.last_pang) >= reconnectTimeout_s;
                if (self.webSocket == null || (now - self.last_pang) > 4) {
                    self.reconnect();
                    self.last_ping = now;
                    self.last_pang = now;
                }
            };

            self.timeout = 2000;
            self.interHeart = setInterval(heartCallback, self.timeout);
        }
    };

    CommonSocket.prototype.reconnect = function () {
        var self = this;
        if (self.needReconnect) {
            console.log("WebSocket need reconnect.");
            //清空心跳定时
            clearInterval(self.interHeart);
            clearInterval(self.interRetry);
            clearInterval(self.interRetry2);
            self.isInHeartCheck = false;
            self.reConnectState = 1;
            self.reconnectLogic(1500);
        }
    };

    CommonSocket.prototype.reconnectLogic = function (retryTime) {
        var self = this;

        function _logic() {
            if (self.reConnectState == 1) {
                self.reConnectCount += 1;
                if(websocketcbObj && (typeof websocketcbObj.onReconnectCallback) == 'function'){
                    websocketcbObj.onReconnectCallback();
                }
                
                console.log('正在重新连接，第' + self.reConnectCount + '次');
                //elf.CommonPrefabMgr.createCommonLoading("正在重新连接，第" + self.reConnectCount + "次", null, 380);
                self.initWs();
                self.initEventHandle();
                if (self.reConnectCount > 5) {
                    $(".justchat-status").html('(未连接)');
                    window.parent.postMessage({type:'imStatus', status: 0},"*");
                }else{
                  $(".justchat-status").html('');
                  window.parent.postMessage({type:'imStatus', status: 1},"*");
                }
                if(!(self.reConnectCount%8)){
                  layer.msg("当前连接已中断，请检查网络")
                }
            }
        }

        self.reconnect1 = setInterval(function () {
            console.log("reconnect.---》" + self.name);
            _logic();
        }, retryTime);
    };

    CommonSocket.prototype.commonProto3Send = function (sendId, msgType, data) {
        var self = this;
        var totalBuffer = self.proto.encode(sendId, msgType, data);
        if (self.webSocket != null && self.webSocket.readyState === WebSocket.OPEN) {
            self.webSocket.send(totalBuffer);
            self.last_ping = Date.parse(new Date()) / 1000;
        }
    };

    exports('CommonSocket', CommonSocket);
});

